Extra: Venue 7 electrics#

If you see a straight line, it’s interpolated missing data. Try the sliders to see detail!

import plotly.graph_objects as go
import numpy as np
import pandas as pd

df = pd.read_csv("venue-7-clampon-data.csv")
df["timestamp"] = pd.to_datetime(df['created_at'])
df = df.fillna(value=0)

phase1trace = go.Scatter(customdata=df, 
                    y=df['field1'], 
                    x = df['timestamp'], 
                    mode='lines', 
                    hoverinfo='all', 
                    name='phase 1',
                    )

phase2trace = go.Scatter(customdata=df, 
                    y=df['field2'], 
                    x = df['timestamp'], 
                    mode='lines', 
                    hoverinfo='all', 
                    name='phase 2',
                    )
phase3trace = go.Scatter(customdata=df, 
                    y=df['field3'], 
                    x = df['timestamp'], 
                    mode='lines', 
                    hoverinfo='all', 
                    name='phase 3',
                    )

g = go.FigureWidget(data=[phase1trace,phase2trace,phase3trace])
g.layout.title = 'CurrentCost clamp-on meter readings'
g.layout.xaxis.title= 'timestamp'
g.layout.yaxis.title = "Watts"
g.layout.width = 1000
g.layout.height = 500

fig = go.Figure(g)

fig.update_layout(
    hovermode='x unified',
    hoverlabel=dict(
        bgcolor="white",
        # font_size=16,
        font_family="Rockwell"
    )
)

# Add range slider
fig.update_layout(
    xaxis=dict(
        rangeselector=dict(
            buttons=list([
                dict(
                     label="All",
                     step="all"
                     ),
                                dict(count=1,
                     label="Hour",
                     step="hour",
                     stepmode="todate"),
                dict(count=1,
                     label="Day",
                     step="day",
                     stepmode="backward"),
                dict(count=7,
                     label="Week",
                     step="day",
                     stepmode="backward"),
                dict(count=1,
                     label="Year",
                     step="year",
                     stepmode="backward")
            ])
        ),
        rangeslider=dict(
            visible=True,
        ),
        type="date"
    )
)


# fig.update_yaxes(range=[50, 60])  



# fig.update_yaxes(range = [-5, df['temperature'].max()+5])

fig.show()

# second figure 

sumtrace = go.Scatter(customdata=df, 
                    y=df['field1'] + df['field2'] + df['field3'], 
                    x = df['timestamp'], 
                    mode='lines', 
                    hoverinfo='all', 
                    name='sum of three phases',
                    )

g2 = go.FigureWidget(data=[sumtrace])
g2.layout.title = 'CurrentCost clamp-on meter readings - simple sum of phases'
g2.layout.xaxis.title= 'timestamp'
g2.layout.yaxis.title = "Watts"
g2.layout.width = 1000
g2.layout.height = 500

fig2 = go.Figure(g2)

fig2.update_layout(
    hovermode='x unified',
    hoverlabel=dict(
        bgcolor="white",
        # font_size=16,
        font_family="Rockwell"
    )
)

# Add range slider
fig2.update_layout(
    xaxis=dict(
        rangeselector=dict(
            buttons=list([
                dict(
                     label="All",
                     step="all"
                     ),
                                dict(count=1,
                     label="Hour",
                     step="hour",
                     stepmode="todate"),
                dict(count=1,
                     label="Day",
                     step="day",
                     stepmode="backward"),
                dict(count=7,
                     label="Week",
                     step="day",
                     stepmode="backward"),
                dict(count=1,
                     label="Year",
                     step="year",
                     stepmode="backward")
            ])
        ),
        rangeslider=dict(
            visible=True,
        ),
        type="date"
    )
)


fig2.show()
---------------------------------------------------------------------------
KeyboardInterrupt                         Traceback (most recent call last)
Cell In[1], line 156
    121 # Add range slider
    122 fig2.update_layout(
    123     xaxis=dict(
    124         rangeselector=dict(
   (...)
    152     )
    153 )
--> 156 fig2.show()

File /opt/hostedtoolcache/Python/3.8.14/x64/lib/python3.8/site-packages/plotly/basedatatypes.py:3398, in BaseFigure.show(self, *args, **kwargs)
   3365 """
   3366 Show a figure using either the default renderer(s) or the renderer(s)
   3367 specified by the renderer argument
   (...)
   3394 None
   3395 """
   3396 import plotly.io as pio
-> 3398 return pio.show(self, *args, **kwargs)

File /opt/hostedtoolcache/Python/3.8.14/x64/lib/python3.8/site-packages/plotly/io/_renderers.py:385, in show(fig, renderer, validate, **kwargs)
    350 def show(fig, renderer=None, validate=True, **kwargs):
    351     """
    352     Show a figure using either the default renderer(s) or the renderer(s)
    353     specified by the renderer argument
   (...)
    383     None
    384     """
--> 385     fig_dict = validate_coerce_fig_to_dict(fig, validate)
    387     # Mimetype renderers
    388     bundle = renderers._build_mime_bundle(fig_dict, renderers_string=renderer, **kwargs)

File /opt/hostedtoolcache/Python/3.8.14/x64/lib/python3.8/site-packages/plotly/io/_utils.py:12, in validate_coerce_fig_to_dict(fig, validate)
      9 from plotly.basedatatypes import BaseFigure
     11 if isinstance(fig, BaseFigure):
---> 12     fig_dict = fig.to_dict()
     13 elif isinstance(fig, dict):
     14     if validate:
     15         # This will raise an exception if fig is not a valid plotly figure

File /opt/hostedtoolcache/Python/3.8.14/x64/lib/python3.8/site-packages/plotly/basedatatypes.py:3289, in BaseFigure.to_dict(self)
   3277 """
   3278 Convert figure to a dictionary
   3279 
   (...)
   3285 dict
   3286 """
   3287 # Handle data
   3288 # -----------
-> 3289 data = deepcopy(self._data)
   3291 # Handle layout
   3292 # -------------
   3293 layout = deepcopy(self._layout)

File /opt/hostedtoolcache/Python/3.8.14/x64/lib/python3.8/copy.py:146, in deepcopy(x, memo, _nil)
    144 copier = _deepcopy_dispatch.get(cls)
    145 if copier is not None:
--> 146     y = copier(x, memo)
    147 else:
    148     if issubclass(cls, type):

File /opt/hostedtoolcache/Python/3.8.14/x64/lib/python3.8/copy.py:205, in _deepcopy_list(x, memo, deepcopy)
    203 append = y.append
    204 for a in x:
--> 205     append(deepcopy(a, memo))
    206 return y

File /opt/hostedtoolcache/Python/3.8.14/x64/lib/python3.8/copy.py:146, in deepcopy(x, memo, _nil)
    144 copier = _deepcopy_dispatch.get(cls)
    145 if copier is not None:
--> 146     y = copier(x, memo)
    147 else:
    148     if issubclass(cls, type):

File /opt/hostedtoolcache/Python/3.8.14/x64/lib/python3.8/copy.py:230, in _deepcopy_dict(x, memo, deepcopy)
    228 memo[id(x)] = y
    229 for key, value in x.items():
--> 230     y[deepcopy(key, memo)] = deepcopy(value, memo)
    231 return y

File /opt/hostedtoolcache/Python/3.8.14/x64/lib/python3.8/copy.py:153, in deepcopy(x, memo, _nil)
    151 copier = getattr(x, "__deepcopy__", None)
    152 if copier is not None:
--> 153     y = copier(memo)
    154 else:
    155     reductor = dispatch_table.get(cls)

File /opt/hostedtoolcache/Python/3.8.14/x64/lib/python3.8/copy.py:142, in deepcopy(x, memo, _nil)
    139 if y is not _nil:
    140     return y
--> 142 cls = type(x)
    144 copier = _deepcopy_dispatch.get(cls)
    145 if copier is not None:

KeyboardInterrupt: 

It’s complicated to know how much electricity is drawn from the three phases of a meter - it’s not just a case of adding the three phases up. But this will give some idea.

This plot is interesting because it shows a minimum of around 2 kW base load with lots of 2.5 kW spikes even when the building is unoccupied. If that electricity isn’t doing useful work, getting those under control could substantially cut the electricity bill. The equipment we are using isn’t very common and we only have one set, but getting a smart meter is another way of seeing this kind of information. Admittedly, with half hourly readings a smart meter isn’t nearly as informative. This is roughly what the same data would look like with a smart meter.



# downsample to every 30 minutes

df.field1 = df.field1.astype(int)
df.field2 = df.field2.astype(int) 
df.field3 = df.field3.astype(int)

# aggregate over 30 minute intervals - this is the interval for smart meter readings.
s = df.resample('30T', on='timestamp', origin='start').agg({'field1':'mean','field2':'mean','field3':'mean'})
s['timestamp'] = s.index 
s = s.fillna(value=0)

downsampled1 = go.Scatter(customdata=s, 
                    y=s['field1']/1000, 
                    x = s['timestamp'], 
                    mode='lines', 
                    hoverinfo='all', 
                    name='phase 1',
                    )
downsampled2 = go.Scatter(customdata=s, 
                    y=s['field2']/1000, 
                    x = s['timestamp'], 
                    mode='lines', 
                    hoverinfo='all', 
                    name='phase 2',
                    )
downsampled3 = go.Scatter(customdata=s, 
                    y=s['field3']/1000, 
                    x = s['timestamp'], 
                    mode='lines', 
                    hoverinfo='all', 
                    name='phase 3',
                    )

g3 = go.FigureWidget(data=[downsampled1, downsampled2, downsampled3])
g3.layout.title = 'CurrentCost clamp-on meter readings - aggregated for half hour slots'
g3.layout.xaxis.title= 'timestamp'
g3.layout.yaxis.title = "kW"
g3.layout.width = 1000
g3.layout.height = 500

fig3 = go.Figure(g3)

fig3.update_layout(
    hovermode='x unified',
    hoverlabel=dict(
        bgcolor="white",
        # font_size=16,
        font_family="Rockwell"
    )
)

# Add range slider
fig3.update_layout(
    xaxis=dict(
        rangeselector=dict(
            buttons=list([
                dict(
                     label="All",
                     step="all"
                     ),
                                dict(count=1,
                     label="Hour",
                     step="hour",
                     stepmode="todate"),
                dict(count=1,
                     label="Day",
                     step="day",
                     stepmode="backward"),
                dict(count=7,
                     label="Week",
                     step="day",
                     stepmode="backward"),
                dict(count=1,
                     label="Year",
                     step="year",
                     stepmode="backward")
            ])
        ),
        rangeslider=dict(
            visible=True,
        ),
        type="date"
    )
)


fig3.show()